widget: Add send_focus_change()
authorEmmanuele Bassi <ebassi@linux.intel.com>
Mon, 12 Apr 2010 13:49:21 +0000 (14:49 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Mon, 26 Apr 2010 17:59:22 +0000 (18:59 +0100)
Currently the only users of the GTK_HAS_FOCUS flag are setting it
before sending a focus change event. This is normally needed by
GtkWindow, but there are widgets that require controlling the focus
of widgets that are semantically their children even though they are
parented to another top-level. Case in point: the quick search entry
for GtkTreeView.

Over the years people have been hacking the focus change out of
gtkwindow.c and gtktreeview.c, thus leaking the direct access of the
GTK_HAS_FOCUS flag.

The simplest way to avoid that is to add a function that sends the
focus change event and controls the setting of the flag, thus removing
the need for external widgets to do the same.

https://bugzilla.gnome.org/show_bug.cgi?id=593671

docs/reference/gtk/gtk-sections.txt
gtk/gtk.symbols
gtk/gtkwidget.c
gtk/gtkwidget.h

index 780d04e67b07165634774d45efc03c72cb6b7349..1961891820bc694136c99496dfbf06d84f48cd8b 100644 (file)
@@ -5683,6 +5683,7 @@ gtk_widget_class_find_style_property
 gtk_widget_class_list_style_properties
 gtk_widget_region_intersect
 gtk_widget_send_expose
+gtk_widget_send_focus_change
 gtk_widget_style_get
 gtk_widget_style_get_property
 gtk_widget_style_get_valist
index 311875f098e9efcb3a4d9ce4325a5d5b2336c16d..b1c04712527c32e886a17931c34f45d72b90a3ed 100644 (file)
@@ -5196,6 +5196,7 @@ gtk_widget_reparent
 gtk_widget_reset_rc_styles
 gtk_widget_reset_shapes
 gtk_widget_send_expose
+gtk_widget_send_focus_change
 gtk_widget_set_accel_path
 gtk_widget_set_allocation
 gtk_widget_set_app_paintable
index 2ee01d970099fbc483ee16c9d2cf76c9f4ce8648..de85182ad57c70d409e1458e766317d236675e04 100644 (file)
@@ -11284,5 +11284,71 @@ gtk_widget_get_window (GtkWidget *widget)
   return widget->window;
 }
 
+static void
+_gtk_widget_set_has_focus (GtkWidget *widget,
+                           gboolean   has_focus)
+{
+  if (has_focus)
+    GTK_OBJECT_FLAGS (widget) |= GTK_HAS_FOCUS;
+  else
+    GTK_OBJECT_FLAGS (widget) &= ~(GTK_HAS_FOCUS);
+}
+
+/**
+ * gtk_widget_send_focus_change:
+ * @widget: a #GtkWidget
+ * @event: a #GdkEvent of type GDK_FOCUS_CHANGE
+ *
+ * Sends the focus change @event to @widget
+ *
+ * This function is not meant to be used by applications. The only time it
+ * should be used is when it is necessary for a #GtkWidget to assign focus
+ * to a widget that is semantically owned by the first widget even though
+ * it's not a direct child - for instance, a search entry in a floating
+ * window similar to the quick search in #GtkTreeView.
+ *
+ * An example of its usage is:
+ *
+ * |[
+ *   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+ *
+ *   fevent->focus_change.type = GDK_FOCUS_CHANGE;
+ *   fevent->focus_change.in = TRUE;
+ *   fevent->focus_change.window = gtk_widget_get_window (widget);
+ *   if (fevent->focus_change.window != NULL)
+ *     g_object_ref (fevent->focus_change.window);
+ *
+ *   gtk_widget_send_focus_change (widget, fevent);
+ *
+ *   gdk_event_free (event);
+ * ]|
+ *
+ * Return value: the return value from the event signal emission: %TRUE
+ *   if the event was handled, and %FALSE otherwise
+ *
+ * Since: 2.20
+ */
+gboolean
+gtk_widget_send_focus_change (GtkWidget *widget,
+                              GdkEvent  *event)
+{
+  gboolean res;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (event != NULL && event->type == GDK_FOCUS_CHANGE, FALSE);
+
+  g_object_ref (widget);
+
+  _gtk_widget_set_has_focus (widget, event->focus_change.in);
+
+  res = gtk_widget_event (widget, event);
+
+  g_object_notify (G_OBJECT (widget), "has-focus");
+
+  g_object_unref (widget);
+
+  return res;
+}
+
 #define __GTK_WIDGET_C__
 #include "gtkaliasdef.c"
index 132079937ea1c73eb48131e81821e2f740b019cd..bf7c3422858bad07cb326b87a6c8bc64c12379a5 100644 (file)
@@ -897,6 +897,8 @@ gboolean   gtk_widget_event           (GtkWidget           *widget,
                                           GdkEvent            *event);
 gint       gtk_widget_send_expose         (GtkWidget           *widget,
                                           GdkEvent            *event);
+gboolean   gtk_widget_send_focus_change   (GtkWidget           *widget,
+                                           GdkEvent            *event);
 
 gboolean   gtk_widget_activate              (GtkWidget        *widget);
 gboolean   gtk_widget_set_scroll_adjustments (GtkWidget        *widget,